using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Text.RegularExpressions;
using XenoGears.Functional;
using XenoGears.Assertions;
using XenoGears.Strings;

namespace Jink.Core.Json.Values
{
    public class JsonExpression : JsonValue
    {
        public String Code { get; set; }
        public Object Value { get { return Eval(); } }

        public JsonExpression(String code)
            : base(true)
        {
            Code = code;
        }

        private Object Eval()
        {
            var code = (Code ?? String.Empty).Trim();
            if (code.IsNullOrEmpty() || code == "null")
            {
                return null;
            }
            else if (Regex.IsMatch(code, "^'.*'$"))
            {
                return code.FromJsonString();
            }
            else if (Regex.IsMatch(code, "^\".*\"$"))
            {
                return code.FromJsonString();
            }
            else
            {
                int integer;
                if (int.TryParse(code, out integer))
                {
                    return integer;
                }

                double floatingPoint;
                if (double.TryParse(code, out floatingPoint))
                {
                    return floatingPoint;
                }

                bool boolean;
                if (bool.TryParse(code, out boolean))
                {
                    return boolean;
                }

                // todo. use Relinq for this with js symbols being resolved to context variable
                // todo. implement proper exception handling (alas, I have no time for this atm)
                // e.g. crash if bad converters
                throw AssertionHelper.Fail();
            }
        }

        public override void BuildCompactString(TextWriter writer)
        {
            writer.Write(Code);
        }

        public override void BuildPrettyString(IndentedTextWriter writer)
        {
            writer.Write(Code);
        }
    }
}